<template>
    <div class="m-sign-box"
         :class="{'m-sign-box-landscape-screen':landscapeScreen}"
         :style="landscapeScreenStyle"
    >
        <Vue3Signature
            :key="refresh"
            id="my-canvas"
            ref="signature"
            :sigOption="option"
            :h="canvasHeight"
            :disabled="disabled"
            class="sing-canvas"
        />
        <div class="m-mini-btn-box">
            <div class="m-mini-btn" type="primary" size="mini" @click="undo">{{i18n('undo','撤销')}}</div>
            <div class="m-mini-btn" type="primary" size="mini" @click="clear">{{i18n('clear','清除')}}</div>
            <div class="m-mini-btn" type="primary" size="mini" @click="save">{{i18n('save','保存')}}</div>
            <div class="m-mini-btn" type="primary" size="mini" @click="close">{{i18n('close','关闭')}}</div>
            <div class="m-mini-btn" type="primary" size="mini" @click="handleLandscapeScreen">{{landscapeScreen?i18n('landscapeScreenYES','竖屏'):i18n('landscapeScreenNO','横屏')}}</div>
        </div>
    </div>
</template>

<script>
//https://blog.csdn.net/m0_61919101/article/details/134883048
//npm install vue3-signature --save-dev
import Vue3Signature from 'vue3-signature'
import { FormApi } from "@/api/FormApi.js";
import dayjs from "dayjs";
import 'dayjs/locale/zh-cn';
dayjs.locale('zh-cn');
export default {
    name: "MSignDialog",
    props:{
        dialogClose:{},
        curUserId:{}
    },
    components:{
        Vue3Signature
    },
    computed:{
        landscapeScreenStyle(){
            if(this.landscapeScreen){
                this.canvasHeight = "100%"
            }else {
                this.canvasHeight = "50%"
                return {}
            }
        }
    },
    data(){
        return {
            canvasHeight:"50%",
            imageType:'image/png',
            disabled:false,
            option: {
                penColor: "#000000",
                backgroundColor: "rgb(255,255,255)"
            },
            landscapeScreen:false,
            refresh:'t',
        }
    },
    created(){
        this.landscapeScreen = false ;
        this.canvasHeight = "100%" ;
        this.$nextTick(()=>{
            this.setRefreshKey()
        })
    },
    methods:{
        i18n(name,text,key){
            return this.$ti18(name,text,"componentsLang",key);
        },
        close(){
            this.dialogClose({})
        },
        getTime(){
            let format = "YYYY-MM-DD HH:mm:ss";
            return dayjs().format(format);
        },
        uploadImg(data){
            let self_ = this ;
            let {penColor} = this.option ;
            FormApi.saveSignature(data, penColor).then(res => {
                if (res.success) {
                    let obj = {
                        'fileId': res.data,
                        'time': self_.getTime(),
                        'userId': self_.curUserId
                    }
                    self_.dialogClose({action:'ok',data:obj})
                }else {
                    uni.showToast({
                        title:this.i18n('Error','出错了'),
                        duration: 2000,
                        icon:'error'
                    })
                    return ;
                }
            })
        },
        getCanvasContentSize(originalCanvas) {
            // 创建一个临时canvas
            var tempCanvas = document.createElement('canvas');
            var tempCtx = tempCanvas.getContext('2d');

            // 设置临时canvas的宽高与原始canvas一样
            tempCanvas.width = originalCanvas.width;
            tempCanvas.height = originalCanvas.height;

            // 将原始canvas的内容绘制到临时canvas上
            tempCtx.drawImage(originalCanvas, 0, 0);

            // 获取内容区域的大小
            var imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
            var data = imageData.data;

            // 查找非透明像素的起始和结束位置
            var startX = tempCanvas.width;
            var startY = tempCanvas.height;
            var endX = 0;
            var endY = 0;

            for (var y = 0; y < tempCanvas.height; y++) {
                for (var x = 0; x < tempCanvas.width; x++) {
                    var index = (y * tempCanvas.width + x) * 4;
                    if (data[index + 3] > 0  && data[index]!== 255) { // 非透明像素
                        if (x < startX) startX = x;
                        if (y < startY) startY = y;
                        if (x > endX) endX = x;
                        if (y > endY) endY = y;
                    }
                }
            }

            // 计算实际内容的宽和高
            var width = endX - startX + 1;
            var height = endY - startY + 1;

            // 返回实际内容的大小
            return { width: width, height: height };
        },
        rotateBase64Img (src, edg) {
            return new Promise((resolve, reject) => {
                const canvas = document.createElement('canvas')
                const ctx = canvas.getContext('2d')
                let imgW // 图片宽度
                let imgH // 图片高度
                let size // canvas初始大小
                if (edg % 90 !== 0) {
                    reject( this.i18n('rotate90','旋转角度必须是90的倍数!'))
                }
                edg < 0 && (edg = (edg % 360) + 360)
                const quadrant = (edg / 90) % 4 // 旋转象限
                const cutCoor = { sx: 0, sy: 0, ex: 0, ey: 0 } // 裁剪坐标
                const image = new Image()
                image.crossOrigin = 'anonymous'
                image.src = src
                image.onload = function () {
                    imgW = image.width
                    imgH = image.height
                    size = imgW > imgH ? imgW : imgH
                    canvas.width = size * 2
                    canvas.height = size * 2
                    switch (quadrant) {
                        case 0:
                            cutCoor.sx = size
                            cutCoor.sy = size
                            cutCoor.ex = size + imgW
                            cutCoor.ey = size + imgH
                            break
                        case 1:
                            cutCoor.sx = size - imgH
                            cutCoor.sy = size
                            cutCoor.ex = size
                            cutCoor.ey = size + imgW
                            break
                        case 2:
                            cutCoor.sx = size - imgW
                            cutCoor.sy = size - imgH
                            cutCoor.ex = size
                            cutCoor.ey = size
                            break
                        case 3:
                            cutCoor.sx = size
                            cutCoor.sy = size - imgW
                            cutCoor.ex = size + imgH
                            cutCoor.ey = size + imgW
                            break
                    }
                    ctx?.translate(size, size)
                    ctx?.rotate((edg * Math.PI) / 180)
                    // drawImage向画布上绘制图片
                    ctx?.drawImage(image, 0, 0)
                    // getImageData() 复制画布上指定矩形的像素数据
                    const imgData = ctx?.getImageData(cutCoor.sx, cutCoor.sy, cutCoor.ex, cutCoor.ey)
                    if (quadrant % 2 == 0) {
                        canvas.width = imgW
                        canvas.height = imgH
                    } else {
                        canvas.width = imgH
                        canvas.height = imgW
                    }
                    // putImageData() 将图像数据放回画布
                    ctx?.putImageData(imgData, 0, 0)

                    const newBase64Str = canvas.toDataURL('image/png', 1.0)
                    resolve(newBase64Str)
                }
            })
        },
        async save(){
            let data = this.$refs.signature.save(this.imageType);
            if(this.$refs.signature.isEmpty()){
                uni.showToast({
                    title:this.i18n('PleaseSignature','请写入签名'),
                    duration: 2000,
                    icon:'error'
                })
                return ;
            }
            if(this.landscapeScreen){
                let signature = this.$refs['signature'].$el ;
                let canvas = signature.querySelector('canvas[id^="canvas"]');
                let bounds = this.getCanvasContentSize(canvas);
                let cropCanvas = document.createElement('canvas');
                cropCanvas.width = bounds.width;
                cropCanvas.height = bounds.height;
                let cropCtx = cropCanvas.getContext('2d');
                // 重新绘制形状到裁剪用的canvas
                cropCtx.drawImage(canvas, 0, 0,bounds.width,bounds.height);
                let base64 = cropCanvas.toDataURL('image/png') ;
                let imgSrc = await this.rotateBase64Img(base64, -90)

                this.uploadImg(imgSrc)
            }else {
                this.uploadImg(data)
            }
        },
        undo(){
            this.$refs.signature.undo();
        },
        clear(){
            this.$refs.signature.clear();
        },
        setRefreshKey(){
            let key = new Date().getTime();
            this.refresh = `t_${key}` ;
        },
        handleLandscapeScreen(){
            this.landscapeScreen = !this.landscapeScreen ;
            this.$nextTick(()=>{
                this.setRefreshKey()
            })
        }
    }
}
</script>

<style scoped>
.my-uni-canvas{
    position: absolute;
    z-index: 1;
    top: 0;
    left: 0;
}
.sing-canvas{
    position: relative;
    z-index: 2;
}
.m-sign-box-landscape-screen{
    transform-origin: left top;
}

.m-sign-box-landscape-screen .m-mini-btn-box{
    position: absolute;
    transform:rotate(90deg) translateX(-100%);
    bottom: 10px;
    left: 10px;
    transform-origin: left bottom;
    border-left: 1px solid #ddd;
    border-right: 1px solid #ddd;
    z-index: 999;
}
.m-sign-box{
    width: 100%;
    height: 100%;
    position: relative;
    background-color: #f4f5f6;
}
.m-mini-btn-box{
    display: flex;
    position: relative;
    z-index: 40;
    background-color: #fff;
}
.m-mini-btn{
    flex: 1;
    text-align: center;
    border-bottom: 1px solid #ddd;
    border-top: 1px solid #ddd;
    padding: .4rem .6rem;
    position: relative;
    z-index: 4;
}
.m-mini-btn:not(:last-child){
    border-right: 1px solid #ddd;
}
</style>
